package de.joergviola.mobj.client;

import java.util.logging.Logger;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.ServiceDefTarget;

import de.joergviola.mobj.client.remote.RemoteTransaction;
import de.joergviola.mobj.client.remote.RemoteTransactionAsync;
import de.joergviola.mobj.client.repl.ReplicatingTransaction;
import de.joergviola.mobj.shared.Schema;

public class MobjStore {
	private LocalDB localDB;
	private RemoteTransactionAsync remote;
	private static final Logger log = Logger.getLogger("Replication");
	private final Schema schema;
	private boolean online = isOnline();
	private boolean remoteOnly;
	private boolean localOnly;

	/**
	 * Creates a synchronizing datastore.
	 * 
	 * @param schema
	 *            The data schema to be used for all operations on this store.
	 */
	public MobjStore(Schema schema) {
		this.schema = schema;
		localDB = new LocalDB(schema);
		remote = createRemoteTransaction();
		if (online) {
			log.info("Replication online");
		} else {
			log.info("Replication offline");
		}
	}

	public Schema getSchema() {
		return schema;
	}

	protected RemoteTransactionAsync createRemoteTransaction() {
		RemoteTransactionAsync remoteTx = GWT.create(RemoteTransaction.class);
		ServiceDefTarget target = (ServiceDefTarget) remoteTx;
		target.setServiceEntryPoint(schema.getRemoteURI());
		return remoteTx;
	}

	public static native boolean isOnline() /*-{
		return navigator.onLine;
	}-*/;

	/**
	 * Creates a synchronizing transaction.
	 * 
	 * @returns The transaction created on the datastore
	 */
	public ITransaction sync() {
		if (!online || localOnly) {
			log.info("Starting local Transaction");
			return local();
		}
		if (remoteOnly) {
			log.info("Starting remote Transaction");
			return remote();
		}
		log.info("Starting sync Transaction");
		return new ReplicatingTransaction(schema,
				localDB.getLocalTransaction(), remote);
	}

	/**
	 * Creates a transaction on the client datastore.
	 * 
	 * @returns The transaction created on the datastore
	 */
	public ITransaction local() {
		log.info("Starting local Transaction");
		return localDB.getLocalTransaction();
	}

	/**
	 * Creates a transaction on the server datastore.
	 * 
	 * @returns The transaction created on the datastore
	 */
	public ITransaction remote() {
		log.info("Starting remote Transaction");
		return remote;
	}

	public void setLocalOnly() {
		localOnly = true;
		remoteOnly = false;
		log.info("Replication set offline");
	}

	public void setRemoteOnly() {
		localOnly = false;
		remoteOnly = true;
		log.info("Replication set online only");
	}

	public void setSynchronising() {
		localOnly = false;
		remoteOnly = false;
		log.info("Replication set online");
	}
}
